package com.floreantpos.bo.actions;

import com.floreantpos.model.MenuItem;
import com.floreantpos.model.Restaurant;
import com.floreantpos.model.Ticket;
import com.floreantpos.model.TicketItem;
import com.floreantpos.model.dao.MenuItemDAO;
import com.floreantpos.model.dao.RestaurantDAO;
import com.floreantpos.model.dao.TicketDAO;
import com.floreantpos.model.util.DateUtil;
import com.floreantpos.util.POSUtil;
import java.awt.event.ActionEvent;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.AbstractAction;
import javax.swing.Icon;
import javax.swing.JOptionPane;


public class RpsSaoPauloAction extends AbstractAction {
  
  Date dataInicialAsDate, dataFinalAsDate;
  
  String dataInicial;
  String dataFinal;
  
  String localDoArquivo;
  
  String fimDeLinha = "\r\n";
  
  Integer qtdLinhasDetalhe = 0;
  
  Double vlrTotalNoArquivo = Double.valueOf(0);
  
  File arquivo;
  
  SimpleDateFormat dataFormatoRps = new SimpleDateFormat("yyyyMMdd", new Locale("pt", "BR"));
  
  DecimalFormat decimalFormat = new DecimalFormat("#,##0.00", new DecimalFormatSymbols(new Locale("pt", "BR")));
  
  List<String> linhasDoArquivo = new ArrayList<String>();

  public RpsSaoPauloAction() {
    super("Lote RPS São Paulo");
  }

  public RpsSaoPauloAction(String name) {
    super(name);
  }

  public RpsSaoPauloAction(String name, Icon icon) {
    super(name, icon);
  }

  @Override
  public void actionPerformed(ActionEvent e) {
    
    dataInicial = JOptionPane.showInputDialog("Data Inicial (dd/mm/aaaa): ");
    dataFinal = JOptionPane.showInputDialog("Data Final (dd/mm/aaaa): ");
    
    if (dataInicial.isEmpty() || dataFinal.isEmpty()) {
      JOptionPane.showMessageDialog(null, "Data Inicial e Final são obrigatórias", com.floreantpos.POSConstants.MDS_POS, JOptionPane.ERROR_MESSAGE, null);
      return;      
    }
    
    try {
      SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd/MM/yyyy", new Locale("pt", "BR"));
      simpleDateFormat.setLenient(false);
      dataInicialAsDate = simpleDateFormat.parse(dataInicial);
      dataFinalAsDate = simpleDateFormat.parse(dataFinal);
    } catch (ParseException ex) {      
      JOptionPane.showMessageDialog(null, "Data(s) Inválida(s)", com.floreantpos.POSConstants.MDS_POS, JOptionPane.ERROR_MESSAGE, null);      
      Logger.getLogger(RpsSaoPauloAction.class.getName()).log(Level.WARNING, null, ex);
      return;      
    }
    
    Calendar calendar = Calendar.getInstance();
    calendar.add(Calendar.DATE, -1);
    if (dataFinalAsDate.after(calendar.getTime())) {
      JOptionPane.showMessageDialog(null, "Data Final deve ser menor que a Data Atual", com.floreantpos.POSConstants.MDS_POS, JOptionPane.ERROR_MESSAGE, null);      
      return;
    }
    
    if (dataInicialAsDate.after(dataFinalAsDate)) {
      JOptionPane.showMessageDialog(null, "Data Inicial deve ser menor que Data Final", com.floreantpos.POSConstants.MDS_POS, JOptionPane.ERROR_MESSAGE, null);      
    } else {
      if(cabecalho() && linhas() && rodape() && geraArquivo()) {
        JOptionPane.showMessageDialog(null, "Arquivo Gerado com sucesso.\n" + localDoArquivo, com.floreantpos.POSConstants.MDS_POS, JOptionPane.INFORMATION_MESSAGE, null);
      } else {
        JOptionPane.showMessageDialog(null, "Falha na Geração do Arquivo", com.floreantpos.POSConstants.MDS_POS, JOptionPane.ERROR_MESSAGE, null);
      }
    }    

  }
  
  private Boolean cabecalho() {
    
    RestaurantDAO restaurantDAO = RestaurantDAO.getInstance();
    Restaurant restaurant = restaurantDAO.get(Integer.valueOf(1));
            
    String tipoRegistro = "1";
    String versaoArquivo = "001";
    String ccm = "";
    
    if (restaurant.getCcm() == null || restaurant.getCcm().isEmpty() 
            || !POSUtil.isNumeric(restaurant.getCcm().replace(".", "").replace("/", "").replace("-", "")) 
            || restaurant.getCcm().replace(".", "").replace("/", "").replace("-", "").length() > 8) {
      
      JOptionPane.showMessageDialog(null, "Verifique se o CCM está cadastrado corretamente", com.floreantpos.POSConstants.MDS_POS, JOptionPane.ERROR_MESSAGE, null);            
      return false;
      
    } else {
      
      ccm = restaurant.getCcm().replace(".", "").replace("/", "").replace("-", "");
      ccm = "00000000".substring(ccm.length()) + ccm;
      
    }
    
    dataInicial = dataFormatoRps.format(dataInicialAsDate);
    
    dataFinal = dataFormatoRps.format(dataFinalAsDate);
    
    String cabecalho = tipoRegistro + versaoArquivo + ccm 
            + dataInicial + dataFinal
            + fimDeLinha;
    
    linhasDoArquivo.add(cabecalho);
    
    return true;
  }
  
  private Boolean rodape() {
      
    if (qtdLinhasDetalhe == 0) {
      JOptionPane.showMessageDialog(null, "Não foram encontrados Cupons Fiscais de Serviço.\nVerifique o intervalo de datas.", com.floreantpos.POSConstants.MDS_POS, JOptionPane.ERROR_MESSAGE, null);            
      return false;
    }
    
    String tipoRegistro = "9";
    
    String qtdLinhasDetalheAsString = "0000000".substring(String.valueOf(qtdLinhasDetalhe).length()) + qtdLinhasDetalhe;
    
    String vlrTotalNoArquivoAsString = decimalFormat.format(vlrTotalNoArquivo);
    vlrTotalNoArquivoAsString = vlrTotalNoArquivoAsString.replace(".", "");
    vlrTotalNoArquivoAsString = vlrTotalNoArquivoAsString.replace(",", "");
    vlrTotalNoArquivoAsString = "000000000000000".substring(vlrTotalNoArquivoAsString.length()) + vlrTotalNoArquivoAsString;

    String vlrTotalDeducoesNoArquivo = "000000000000000";
    
    String rodape = tipoRegistro + qtdLinhasDetalheAsString + vlrTotalNoArquivoAsString 
            + vlrTotalDeducoesNoArquivo + fimDeLinha;
    
    linhasDoArquivo.add(rodape);
    
    return true;
  }
  
  private Boolean linhas() {
    
    String tipoRegistro = "3";
    String tipoRps = "RPS-C";
    String serieRps = "00000";
    String numeroRps = "";
    String dataEmissao = "";
    String situacao = "";
    String vlrServicos = "";
    String vlrDeducoes = "000000000000000";
    String codServico = "";
    String aliquota = "";
    String issRetido = "2";
    String indicadorCpfCnpj = "";
    String cpfCnpj = "";
    String descriminacaoServico = "";
    
    MenuItemDAO menuItemDAO = new MenuItemDAO();
    MenuItem menuItem = null;
        
    TicketDAO ticketDAO = new TicketDAO();
    List<Ticket> tickets = ticketDAO.findTicketsWithCupomFiscal(dataInicialAsDate, DateUtil.addDays(dataFinalAsDate, 1), false);
    
    for (Ticket ticket : tickets) {
      List<TicketItem> ticketItens = ticket.getTicketItems();
      int contadorServico = 0;
      for (TicketItem ticketItem : ticketItens) {
        if (ticketItem.isServiceItem() && (ticketItem.getSubtotalAmount() - ticket.getDiscountAmount()) > 0) {
          menuItem = menuItemDAO.find(ticketItem.getItemId(), false);
          
          numeroRps = ticket.getCupomFiscal() + contadorServico;
          numeroRps = "000000000000".substring(numeroRps.length()) + numeroRps;
          
          dataEmissao = dataFormatoRps.format(ticket.getClosingDate());
          
          if (ticket.isCupomFiscalCancelado()) {
            situacao = "C";
          } else {
            situacao = "T";
          }
          
          double vlrServicosAsDouble = ticketItem.getSubtotalAmount() - ticket.getDiscountAmount();
          
          vlrServicos = decimalFormat.format(vlrServicosAsDouble);
          vlrServicos = vlrServicos.replace(".", "");
          vlrServicos = vlrServicos.replace(",", "");
          vlrServicos = "000000000000000".substring(vlrServicos.length()) + vlrServicos;          
                   
          if (!POSUtil.isNumeric(menuItem.getAdditionalReference()) || menuItem.getAdditionalReference().length() != 5) {
            JOptionPane.showMessageDialog(null, "Verifique o campo \"Referência\" no cadastro do item.\n"
                    + "Este campo deve conter o código do serviço com 5 posições.\n"
                    + "Item: " + menuItem.getId() + " - " + menuItem.getName(), com.floreantpos.POSConstants.MDS_POS, JOptionPane.ERROR_MESSAGE, null);            
            return false;
          } else {
            codServico = menuItem.getAdditionalReference();
          }
          
          aliquota = decimalFormat.format(ticketItem.getEcfTaxRate());
          aliquota = aliquota.replace(".", "");
          aliquota = aliquota.replace(",", "");
          aliquota = "0000".substring(aliquota.length()) + aliquota;          
          
          if (ticket.getTaxId() == null || ticket.getTaxId().isEmpty()) {
            indicadorCpfCnpj = "3";
          } else if (ticket.getTaxId().length() > 14) {
            indicadorCpfCnpj = "2"; 
          } else {
            indicadorCpfCnpj = "1";             
          }
          
          if (!indicadorCpfCnpj.equals("3")) {
            cpfCnpj = ticket.getTaxId().replace(".", "").replace("-", "").replace("/", "");
            cpfCnpj = "00000000000000".substring(cpfCnpj.length()) + cpfCnpj;
          } else {
            cpfCnpj = "00000000000000";            
          }
          
          descriminacaoServico = ticketItem.getName();
          
          String linha = tipoRegistro + tipoRps + serieRps + numeroRps + dataEmissao 
                  + situacao + vlrServicos + vlrDeducoes + codServico
                  + aliquota + issRetido + indicadorCpfCnpj + cpfCnpj + descriminacaoServico
                  + fimDeLinha;
          
          linhasDoArquivo.add(linha);
          vlrTotalNoArquivo += vlrServicosAsDouble; 
          qtdLinhasDetalhe++;
          contadorServico++;          
        }
      }
    }
    return true;
  }
  
  private Boolean geraArquivo() {

    String nomeDoArquivo = "export/LoteRpsSaoPaulo-" + dataInicial + "-"
            + dataFinal + ".txt";    
    
    BufferedWriter writer = null;
    try {      
        arquivo = new File(nomeDoArquivo);
        localDoArquivo = arquivo.getCanonicalPath();          
        writer = new BufferedWriter(new FileWriter(arquivo));
        
        for (String linha : linhasDoArquivo) {
            writer.write(linha);
        }
    } catch (IOException e) {
      JOptionPane.showMessageDialog(null, "Falha na gravação do Arquivo.\nMensagem: " + e, com.floreantpos.POSConstants.MDS_POS, JOptionPane.ERROR_MESSAGE, null);
      return false;
    } finally {
        try {
          writer.close();             
        } catch (IOException e) {
          JOptionPane.showMessageDialog(null, "Falha na gravação do Arquivo.\nMensagem: " + e, com.floreantpos.POSConstants.MDS_POS, JOptionPane.ERROR_MESSAGE, null);                      
          return false;
        }
    }    
    
    return true;
  }
}
